﻿using System;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;

namespace <YourNameSpace>
{

	/// <summary>
	/// Interaction logic for Edit.xaml
	/// </summary>
	public partial class Edit : Window
	{
		public object newEntityObject;
		private bool hasChanged = false;
		private bool hasErrors = false;

		
		/// <summary>
		/// EntityObject Edit form
		/// </summary>
		/// <param name="param">EntityObject source</param>
		/// <param name="title">Title of the edit window</param>
		public Edit(EntityObject param, string title)
		{
			this.Title = title;
			InitializeComponent();
			LoadForm(param);
		}

		private void LoadForm(EntityObject param)
		{
			newEntityObject = Activator.CreateInstance(param.GetType());
			PropertyInfo[] properties = newEntityObject.GetType().GetProperties().Where(
				pi => !(pi.PropertyType.IsSubclassOf(typeof(EntityObject)))
					&& !(pi.PropertyType.IsSubclassOf(typeof(EntityReference)))
					&& !(pi.PropertyType.IsSubclassOf(typeof(EdmEntityTypeAttribute)))
					&& !(pi.PropertyType.Name == "EntityState")
					&& !(pi.PropertyType.Name == "EntityKey")
					).ToArray();

			StackPanel panel = new StackPanel();
			panel.MinWidth = 200;

			foreach (PropertyInfo property in properties)
			{
				if (property.CanRead && property.CanWrite)
				{
					newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, param.GetType().GetProperty(property.Name).GetValue(param));
				}

				TextBlock label = new TextBlock();
				label.Text = property.Name;
				panel.Children.Add(label);
				string type = property.PropertyType.Name;
				switch (type)
                {
                    case "Int32":
                        {
                            TextBox input = new TextBox();
                            input.Text = property.GetValue(newEntityObject).ToString();
                            input.IsEnabled = property.CanWrite;
                            input.LostFocus += (obj, args) =>
                            {
                                Int32 value;
                                if (Int32.TryParse(input.Text, out value))
                                {
                                    if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as Int32? != value)
                                    {
                                        newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, value);
                                        hasChanged = true;
                                    }
                                }
                                else
                                {
                                    MessageBox.Show("Can't convert " + input.Text + " to a number.", "Error", MessageBoxButton.OK);
                                    hasErrors = true;
                                }
                            };
                            panel.Children.Add(input);
                            break;
                        };
                    case "Int64":
                        {
                            TextBox input = new TextBox();
                            input.Text = property.GetValue(newEntityObject).ToString();
                            input.IsEnabled = property.CanWrite;
                            input.LostFocus += (obj, args) =>
                            {
                                Int64 value;
                                if (Int64.TryParse(input.Text, out value))
                                {
                                    if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as Int64? != value)
                                    {
                                        newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, value);
                                        hasChanged = true;
                                    }
                                }
                                else
                                {
                                    MessageBox.Show("Can't convert " + input.Text + " to a number.", "Error", MessageBoxButton.OK);
                                    hasErrors = true;
                                }
                            };
                            panel.Children.Add(input);
                            break;
                        };
                    case "float":
                        {
                            TextBox input = new TextBox();
                            input.Text = property.GetValue(newEntityObject).ToString();
                            input.IsEnabled = property.CanWrite;
                            input.LostFocus += (obj, args) =>
                            {
                                float value;
                                if (float.TryParse(input.Text, out value))
                                {
                                    if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as float? != value)
                                    {
                                        newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, value);
                                        hasChanged = true;
                                    }
                                }
                                else
                                {
                                    MessageBox.Show("Can't convert " + input.Text + " to a number.", "Error", MessageBoxButton.OK);
                                    hasErrors = true;
                                }
                            };
                            panel.Children.Add(input);
                            break;
                        }
                    case "Double":
                        {
                            TextBox input = new TextBox();
                            input.Text = property.GetValue(newEntityObject).ToString();
                            input.IsEnabled = property.CanWrite;
                            input.LostFocus += (obj, args) =>
                            {
                                double value;
                                if (double.TryParse(input.Text, out value))
                                {
                                    if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as double? != value)
                                    {
                                        newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, value);
                                        hasChanged = true;
                                    }
                                }
                                else
                                {
                                    MessageBox.Show("Can't convert " + input.Text + " to a number.", "Error", MessageBoxButton.OK);
                                    hasErrors = true;
                                }
                            };
                            panel.Children.Add(input);
                            break;
                        }
                    case "String":
                        {
                            TextBox input = new TextBox();
                            input.Text = property.GetValue(newEntityObject).ToString();
                            input.IsEnabled = property.CanWrite;
                            input.LostFocus += (obj, args) =>
                            {
                                if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject).ToString() != input.Text)
                                {
                                    newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, input.Text);
                                    hasChanged = true;
                                }
                            };
                            panel.Children.Add(input);
                            break;
                        }
                    case "DateTime":
                        {
                            DatePicker picker = new DatePicker();
                            picker.SelectedDate = newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as DateTime?;
                            picker.IsEnabled = property.CanWrite;
                            picker.SelectedDateChanged += (obj, args) =>
                            {
                                if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as DateTime? != picker.SelectedDate)
                                {
                                    newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, picker.SelectedDate);
                                    hasChanged = true;
                                }
                            };
                            panel.Children.Add(picker);
                            break;
                        }
                    case "Boolean":
                        {
                            CheckBox checkbox = new CheckBox();
                            checkbox.IsEnabled = property.CanWrite;
                            checkbox.Content = property.Name;
                            checkbox.IsChecked = newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as bool?;
                            checkbox.Unchecked += (obj, args) =>
                            {
                                if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as bool? != checkbox.IsChecked)
                                {
                                    newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, checkbox.IsChecked);
                                    hasChanged = true;
                                }
                            };
                            checkbox.Checked += (obj, args) =>
                            {
                                if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject) as bool? != checkbox.IsChecked)
                                {
                                    newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, checkbox.IsChecked);
                                    hasChanged = true;
                                }
                            };
                            panel.Children.Add(checkbox);
                            break;
                        }
                    default:
                        {
                            TextBox input = new TextBox();
                            input.Text = property.GetValue(newEntityObject).ToString();
                            input.IsEnabled = property.CanWrite;
                            input.LostFocus += (obj, args) =>
                            {
                                if (newEntityObject.GetType().GetProperty(property.Name).GetValue(newEntityObject).ToString() != input.Text)
                                {
                                    newEntityObject.GetType().GetProperty(property.Name).SetValue(newEntityObject, input.Text);
                                    hasChanged = true;
                                }
                            };
                            panel.Children.Add(input);
                            break;
                        }
                }
			}
			

			StackPanel buttons = new StackPanel();
			buttons.Orientation = Orientation.Horizontal;
			buttons.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
			Button OK = new Button();
			OK.Margin = new Thickness(0, 0, 5, 0);
			OK.Content = "Save";
			OK.Click += (obj, args) =>
				{
					if (hasErrors == false)
					{
						this.DialogResult = hasChanged;
						this.Close();
					}
					else if (MessageBox.Show("Error(s) found. Can't save changes.\nDo you want to exit anyway?", "Warning", MessageBoxButton.YesNo) == true)
					{
						this.DialogResult = false;
						this.Close();
					}
				};
			Button Cancel = new Button();
			Cancel.Content = "Cancel";
			Cancel.Click += (obj, args) =>
				{
					this.DialogResult = false;
					this.Close();
				};
			buttons.Children.Add(OK);
			buttons.Children.Add(Cancel);
			panel.Children.Add(buttons);
			Container.Children.Add(panel);
			this.Buttons = null;
		}
	}

}